package com.fulu.game.bi.service.impl.statistics;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.fulu.game.bi.common.util.OssUtil;
import com.fulu.game.bi.entity.bo.channel.DictItemBO;
import com.fulu.game.bi.entity.bo.channel.GameCategoryListBO;
import com.fulu.game.bi.entity.bo.channel.GameOverviewListBO;
import com.fulu.game.bi.entity.dto.VoiceOverviewListDTO;
import com.fulu.game.bi.entity.overview.ActiveUser;
import com.fulu.game.bi.entity.overview.Broadcast;
import com.fulu.game.bi.entity.overview.Company;
import com.fulu.game.bi.entity.overview.GamePlay;
import com.fulu.game.bi.entity.overview.NewUser;
import com.fulu.game.bi.entity.overview.Party;
import com.fulu.game.bi.entity.po.DictItem;
import com.fulu.game.bi.entity.po.market.HistoryTrendStat;
import com.fulu.game.bi.entity.po.roi.NewAddUserStat;
import com.fulu.game.bi.entity.vo.market.CommonlyQueryVO;
import com.fulu.game.bi.entity.vo.market.NewAddUserQueryVO;
import com.fulu.game.bi.entity.vo.play.GameCategoryStatVO;
import com.fulu.game.bi.entity.vo.play.GameOverviewListVO;
import com.fulu.game.bi.entity.vo.room.VoiceOverviewVO;
import com.fulu.game.bi.mysql.bi.DictItemDao;
import com.fulu.game.bi.redis.service.market.HistoryTrendStatService;
import com.fulu.game.bi.redis.service.market.NewAddUserService;
import com.fulu.game.bi.redis.service.play.GameCategoryService;
import com.fulu.game.bi.redis.service.play.GameOverviewService;
import com.fulu.game.bi.redis.service.statistics.FundsStatisticsService;
import com.fulu.game.bi.service.impl.room.VoiceOverviewService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author: liuxiao
 * @Date: 2021/7/27 6:59 下午
 */
@Slf4j
@Service
public class FundsStatisticsServiceImpl implements FundsStatisticsService {

    @Autowired
    private JdbcTemplate hiveJdbcTemplate;
    @Autowired
    private DictItemDao dictItemDao;
    @Autowired
    private GameOverviewService gameOverviewService;
    @Autowired
    private NewAddUserService newAddUserService;
    @Autowired
    private VoiceOverviewService voiceOverviewService;
    @Autowired
    private HistoryTrendStatService historyTrendStatService;
    @Autowired
    private GameCategoryService gameCategoryService;

    @Autowired
    private OssUtil ossUtil;

    @Override
    public String getFundStatisticsFile() {
        TemplateExportParams params = new TemplateExportParams();
        // 标题开始行
        params.setHeadingStartRow(2);
        // 标题行数
        params.setHeadingRows(1);
        // 设置sheetName，若不设置该参数，则使用得原本得sheet名称
        params.setSheetName("数据统计");

        // 获取报表内容
        // 因为表数据是根据存储过程来实现的，不同的报表有不同的配置，
        // 所以使用Map<String,Object>格式来接收
        Map<String, Object> data = jdbcSelect();

        // 获取模板文件路径
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setCode("FUNDS_FILE_URL");
        String filePath = dictItemDao.findByParameter(dictItemBO).get(0).getVal();
        // 设置模板路径
        params.setTemplateUrl(filePath);
        // 获取workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        // exportFileName代表导出的文件名称
        return this.upload(workbook, "资金报表.xlsx");
    }

    @Override
    public String getIncomeFile() {
        TemplateExportParams params = new TemplateExportParams();
        // 标题开始行
        params.setHeadingStartRow(2);
        // 标题行数
        params.setHeadingRows(1);
        // 设置sheetName，若不设置该参数，则使用得原本得sheet名称
        params.setSheetName("数据统计");

        // 获取报表内容
        // 因为表数据是根据存储过程来实现的，不同的报表有不同的配置，
        // 所以使用Map<String,Object>格式来接收
        Map<String, Object> data = incomeSelect();

        // 获取模板文件路径
        // 获取模板文件路径
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setCode("INCOME_FILE_URL");
        String filePath = dictItemDao.findByParameter(dictItemBO).get(0).getVal();
        // 设置模板路径
        params.setTemplateUrl(filePath);
        // 获取workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        // exportFileName代表导出的文件名称
        return this.upload(workbook, "营收报表.xlsx");
    }

    @Override
    public String getOverviewFile() {

        TemplateExportParams params = new TemplateExportParams();
        // 标题开始行
        params.setHeadingStartRow(2);
        // 标题行数
        params.setHeadingRows(1);
        // 设置sheetName，若不设置该参数，则使用得原本得sheet名称
        params.setSheetName("数据统计");
        Map<String, Object> resultMap = overViewSelect();
        // 获取报表内容
        // 因为表数据是根据存储过程来实现的，不同的报表有不同的配置，
        // 所以使用Map<String,Object>格式来接收
        // 设置模板路径
        // 获取模板文件路径
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setCode("OVERVIEW_FILE_URL");
        String filePath = dictItemDao.findByParameter(dictItemBO).get(0).getVal();

        params.setTemplateUrl(filePath);
        // 获取workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, resultMap);
        // exportFileName代表导出的文件名称
        return upload(workbook, "业务总览.xlsx");
    }

    private Map<String, Object> incomeSelect() {
        Map<String, Object> data = new HashMap<>();
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setDictCode("INCOME_EXPORT");
        List<DictItem> dictItemList = dictItemDao.findByParameter(dictItemBO);
        for (DictItem item : dictItemList) {
            String value = item.getVal();
            System.out.println("item:" + item.getCode() + "," + value);
            List<Map<String, Object>> list = hiveJdbcTemplate.queryForList(value);

            List<Map<String, Object>> result1 = new ArrayList<>();
            List<Map<String, Object>> result2 = new ArrayList<>();
            List<Map<String, Object>> result3 = new ArrayList<>();
            List<Map<String, Object>> result4 = new ArrayList<>();
            List<Map<String, Object>> result5 = new ArrayList<>();

            Map<String, Object> objectMap1 = new HashMap<>();
            Map<String, Object> objectMap2 = new HashMap<>();
            Map<String, Object> objectMap3 = new HashMap<>();
            Map<String, Object> objectMap4 = new HashMap<>();
            Map<String, Object> objectMap5 = new HashMap<>();
            for (Map<String, Object> map : list) {
                Integer flag = (Integer) map.get("flag");

                Object userCount = map.get("user_num") == null ? 0 : map.get("user_num");
                Object sumNum = map.get("count_num") == null ? 0 : map.get("count_num");
                Object sumMoney = map.get("price_sum") == null ? 0 : map.get("price_sum");
                Object charmSumMoney = map.get("charm_sum") == null ? 0 : map.get("charm_sum");
                Object incomeSumMoney = map.get("income") == null ? 0 : map.get("income");

                objectMap1.put("user_num" + "_" + flag, userCount);
                objectMap2.put("count_num" + "_" + flag, sumNum);
                objectMap3.put("price_sum" + "_" + flag, sumMoney);
                objectMap4.put("charm_sum" + "_" + flag, charmSumMoney);
                objectMap5.put("income" + "_" + flag, incomeSumMoney);

            }

            // 环比
            BigDecimal userCount1 = objectMap1.get("user_num_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_num_1").toString());
            BigDecimal userCount2 = objectMap1.get("user_num_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_num_2").toString());
            BigDecimal userCount8 = objectMap1.get("user_num_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_num_8").toString());
            objectMap1.put("user_num_day", userCount2.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", userCount1.subtract(userCount2).divide(userCount2, 4, RoundingMode.DOWN).doubleValue()));
            objectMap1.put("user_num_week", userCount8.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", userCount1.subtract(userCount8).divide(userCount8, 4, RoundingMode.DOWN).doubleValue()));

            BigDecimal sumNum1 = objectMap2.get("count_num_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("count_num_1").toString());
            BigDecimal sumNum2 = objectMap2.get("count_num_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("count_num_2").toString());
            BigDecimal sumNum8 = objectMap2.get("count_num_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("count_num_8").toString());
            objectMap2.put("count_num_day", sumNum2.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", sumNum1.subtract(sumNum2).divide(sumNum2, 4, RoundingMode.DOWN).doubleValue()));
            objectMap2.put("count_num_week", sumNum8.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", sumNum1.subtract(sumNum8).divide(sumNum8, 4, RoundingMode.DOWN).doubleValue()));


            BigDecimal sumMoney1 = objectMap3.get("price_sum_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("price_sum_1").toString());
            BigDecimal sumMoney2 = objectMap3.get("price_sum_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("price_sum_2").toString());
            BigDecimal sumMoney8 = objectMap3.get("price_sum_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("price_sum_8").toString());
            objectMap3.put("price_sum_day", sumMoney2.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", sumMoney1.subtract(sumMoney2).divide(sumMoney2, 4, RoundingMode.DOWN).doubleValue()));
            objectMap3.put("price_sum_week", sumMoney8.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", sumMoney1.subtract(sumMoney8).divide(sumMoney8, 4, RoundingMode.DOWN).doubleValue()));


            BigDecimal charmSumMoney1 = objectMap4.get("charm_sum_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("charm_sum_1").toString());
            BigDecimal charmSumMoney2 = objectMap4.get("charm_sum_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("charm_sum_2").toString());
            BigDecimal charmSumMoney8 = objectMap4.get("charm_sum_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("charm_sum_8").toString());
            objectMap4.put("charm_sum_day", charmSumMoney2.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", charmSumMoney1.subtract(charmSumMoney2).divide(charmSumMoney2, 4, RoundingMode.DOWN).doubleValue()));
            objectMap4.put("charm_sum_week", charmSumMoney8.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", charmSumMoney1.subtract(charmSumMoney8).divide(charmSumMoney8, 4, RoundingMode.DOWN).doubleValue()));


            BigDecimal incomeSumMoney1 = objectMap5.get("income_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap5.get("income_1").toString());
            BigDecimal incomeSumMoney2 = objectMap5.get("income_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap5.get("income_2").toString());
            BigDecimal incomeSumMoney8 = objectMap5.get("income_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap5.get("income_8").toString());
            objectMap5.put("income_day", incomeSumMoney2.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", incomeSumMoney1.subtract(incomeSumMoney2).divide(incomeSumMoney2, 4, RoundingMode.DOWN).doubleValue()));
            objectMap5.put("income_week", incomeSumMoney8.compareTo(BigDecimal.ZERO) == 0 ? "0.00%" : NumberUtil.decimalFormat("#.##%", incomeSumMoney1.subtract(incomeSumMoney8).divide(incomeSumMoney8, 4, RoundingMode.DOWN).doubleValue()));


            result1.add(objectMap1);
            result2.add(objectMap2);
            result3.add(objectMap3);
            result4.add(objectMap4);
            result5.add(objectMap5);

            data.put(item.getCode() + "_user_num", result1);
            data.put(item.getCode() + "_count_num", result2);
            data.put(item.getCode() + "_price_sum", result3);
            data.put(item.getCode() + "_charm_sum", result4);
            data.put(item.getCode() + "_income", result5);
        }
        return data;
    }

    // Excel 导出 通过浏览器下载的形式
    public String upload(Workbook workbook, String fileName) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            workbook.write(bos);
            byte[] bytes = bos.toByteArray();
            InputStream is = new ByteArrayInputStream(bytes);
            String url = ossUtil.uploadFileCustom(is, fileName);
            log.info("url:{}", url);
            return url;
        } catch (IOException e) {
            log.error("error:{}", e);
        }
        return "";
    }

    private Map<String, Object> jdbcSelect() {
        Map<String, Object> data = new HashMap<>();
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setDictCode("FUNDS_EXPORT");
        List<DictItem> dictItemList = dictItemDao.findByParameter(dictItemBO);
        for (DictItem item : dictItemList) {
            String value = item.getVal();
            System.out.println("item:" + item.getCode() + "," + value);
            List<Map<String, Object>> list = hiveJdbcTemplate.queryForList(value);

            List<Map<String, Object>> result1 = new ArrayList<>();
            List<Map<String, Object>> result2 = new ArrayList<>();
            List<Map<String, Object>> result3 = new ArrayList<>();
            List<Map<String, Object>> result4 = new ArrayList<>();

            Map<String, Object> objectMap1 = new HashMap<>();
            Map<String, Object> objectMap2 = new HashMap<>();
            Map<String, Object> objectMap3 = new HashMap<>();
            Map<String, Object> objectMap4 = new HashMap<>();
            for (Map<String, Object> map : list) {
                Integer flag = (Integer) map.get("flag");

                Object userCount = map.get("user_count") == null ? 0 : map.get("user_count");
                Object sumNum = map.get("sum_num") == null ? 0 : map.get("sum_num");
                Object sumMoney = map.get("sum_money") == null ? 0 : map.get("sum_money");
                Object incomeSumMoney = map.get("income_sum_money") == null ? 0 : map.get("income_sum_money");

                objectMap1.put("user_count" + "_" + flag, new BigDecimal(userCount.toString()).abs());
                objectMap2.put("sum_num" + "_" + flag, new BigDecimal(sumNum.toString()).abs());
                objectMap3.put("sum_money" + "_" + flag, new BigDecimal(sumMoney.toString()).abs().setScale(2, RoundingMode.UP));

                if (null != incomeSumMoney) {
                    objectMap4.put("income_sum_money" + "_" + flag, new BigDecimal(incomeSumMoney.toString()).setScale(2, RoundingMode.UP));
                }
            }

            // 环比
            BigDecimal userCount1 = objectMap1.get("user_count_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_count_1").toString());
            BigDecimal userCount2 = objectMap1.get("user_count_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_count_2").toString());
            BigDecimal userCount8 = objectMap1.get("user_count_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap1.get("user_count_8").toString());
            objectMap1.put("user_count_day", userCount2.compareTo(BigDecimal.ZERO) == 0 ? "0%" : userCount1.subtract(userCount2).divide(userCount2, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            objectMap1.put("user_count_week", userCount8.compareTo(BigDecimal.ZERO) == 0 ? "0%" : userCount1.subtract(userCount8).divide(userCount8, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");

            BigDecimal sumNum1 = objectMap2.get("sum_num_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("sum_num_1").toString());
            BigDecimal sumNum2 = objectMap2.get("sum_num_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("sum_num_2").toString());
            BigDecimal sumNum8 = objectMap2.get("sum_num_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap2.get("sum_num_8").toString());
            objectMap2.put("sum_num_day", sumNum2.compareTo(BigDecimal.ZERO) == 0 ? "0%" : sumNum1.subtract(sumNum2).divide(sumNum2, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            objectMap2.put("sum_num_week", sumNum8.compareTo(BigDecimal.ZERO) == 0 ? "0%" : sumNum1.subtract(sumNum8).divide(sumNum8, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");


            BigDecimal sumMoney1 = objectMap3.get("sum_money_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("sum_money_1").toString());
            BigDecimal sumMoney2 = objectMap3.get("sum_money_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("sum_money_2").toString());
            BigDecimal sumMoney8 = objectMap3.get("sum_money_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap3.get("sum_money_8").toString());
            objectMap3.put("sum_money_day", sumMoney2.compareTo(BigDecimal.ZERO) == 0 ? "0%" : sumMoney1.subtract(sumMoney2).divide(sumMoney2, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            objectMap3.put("sum_money_week", sumMoney8.compareTo(BigDecimal.ZERO) == 0 ? "0%" : sumMoney1.subtract(sumMoney8).divide(sumMoney8, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");


            if (MapUtils.isNotEmpty(objectMap4)) {
                BigDecimal incomeSumMoney1 = objectMap4.get("income_sum_money_1") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("income_sum_money_1").toString());
                BigDecimal incomeSumMoney2 = objectMap4.get("income_sum_money_2") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("income_sum_money_2").toString());
                BigDecimal incomeSumMoney8 = objectMap4.get("income_sum_money_8") == null ? BigDecimal.ZERO : new BigDecimal(objectMap4.get("income_sum_money_8").toString());
                objectMap4.put("income_sum_money_day", incomeSumMoney2.compareTo(BigDecimal.ZERO) == 0
                        ? "0%" : incomeSumMoney1.subtract(incomeSumMoney2).divide(incomeSumMoney2, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
                objectMap4.put("income_sum_money_week", incomeSumMoney8.compareTo(BigDecimal.ZERO) == 0
                        ? "0%" : incomeSumMoney1.subtract(incomeSumMoney8).divide(incomeSumMoney8, 4, RoundingMode.UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            }

            result1.add(objectMap1);
            result2.add(objectMap2);
            result3.add(objectMap3);
            result4.add(objectMap4);

            data.put(item.getCode() + "_user_count", result1);
            data.put(item.getCode() + "_sum_num", result2);
            data.put(item.getCode() + "_sum_money", result3);
            data.put(item.getCode() + "_income_sum_money", result4);
        }
        return data;
    }

    @Override
    public void refreshTable() {
        List<String> list = Arrays.asList("ods.bdl_game_t_virtual_product_order ", "ods.bdl_game_t_lottery_order ",
                "ods.bdl_game_t_lottery_order_detail ", "stg.t_fragment_order", "stg.t_fragment_shop_order", "ods.bdl_game_t_cash_draws",
                "ods.bdl_game_t_guild_cash_draws", "ods.bdl_game_t_money_details",
                "ods.bdl_game_t_virtual_details", "ods.bdl_game_t_guild_charge_details", "ods.bdl_game_t_guild_income_details",
                "ods.bdl_game_t_income_details", "ods.bdl_game_t_order", "ods.bdl_game_apple_refund");
        list.forEach(map -> {
            String refreshSql = "refresh " + map;
            hiveJdbcTemplate.execute(refreshSql);
        });
    }


    public Map<String, Object> overViewSelect() {
        Map<String, Object> resultMap = new HashMap<>();
        BigDecimal percentage = BigDecimal.valueOf(100);

        NewAddUserQueryVO query = new NewAddUserQueryVO();
        query.setPageNum(1);
        query.setPageSize(9999);

        query.setQueryType(1);

        DateTime statTimeStart = DateUtil.offsetDay(DateUtil.yesterday(), -7);
        DateTime statTimeEnd = DateUtil.yesterday();

        query.setStatTimeStart(statTimeStart);
        query.setStatTimeEnd(statTimeEnd);

        AtomicInteger flag = new AtomicInteger(1);

//        新用户

        List<NewUser> newUser = newAddUserService.list(query).stream()
                .sorted(Comparator.<NewAddUserStat>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed()).map(l -> {
                    NewUser n = new NewUser();
                    BeanUtil.copyProperties(l, n);
                    n.setConsumeMoneyConvert(BigDecimal.valueOf(n.getInvestUserAll())
                            .multiply(percentage)
                            .divide(BigDecimal.valueOf(n.getNewRegistUserNum()), 2, RoundingMode.DOWN)
                    );
                    n.setInvestMoneyConvert(BigDecimal.valueOf(n.getConsumeUserAll())
                            .multiply(percentage)
                            .divide(BigDecimal.valueOf(n.getNewRegistUserNum()), 2, RoundingMode.DOWN)
                    );
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] newUserNum = new String[]{"newActiveUserNum", "newRegistUserNum", "investUserAll", "investMoneyAll", "investMoneyConvert", "consumeUserAll", "consumeMoneyAll", "consumeMoneyConvert"};
        listToMap("NewUser", newUserNum, newUser, resultMap);


//        活跃用户
        flag.set(1);

        CommonlyQueryVO trend = new CommonlyQueryVO();
        BeanUtil.copyProperties(query, trend);
        trend.setStatTimeStart(statTimeStart);
        trend.setStatTimeEnd(statTimeEnd);

        List<ActiveUser> activeUser = historyTrendStatService.list(trend).stream()
                .sorted(Comparator.<HistoryTrendStat>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed())
                .map(l -> {
                    ActiveUser n = new ActiveUser();
                    BeanUtil.copyProperties(l, n);
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] activeUserNum = new String[]{"livelyUserNum", "investUserAll", "investNum", "investMoneyAll", "consumeUserAll", "consumeNum", "consumeMoneyAll"
                , "pipiMoneyInvestUserNum", "pipiMoneyInvestNum", "pipiMoneyInvestAll", "virtualMoneyInvestUserNum", "virtualMoneyInvestNum", "virtualMoneyInvestAll"};
        listToMap("ActiveUser", activeUserNum, activeUser, resultMap);
//        游戏陪玩
        flag.set(1);

        GameOverviewListBO gameOverview = new GameOverviewListBO();
        BeanUtil.copyProperties(query, gameOverview);
        gameOverview.setStartDate(DateUtil.formatDate(statTimeStart));
        gameOverview.setEndDate(DateUtil.formatDate(statTimeEnd));

        List<GamePlay> gamePlay = gameOverviewService.list(gameOverview).stream()
                .sorted(Comparator.<GameOverviewListVO>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed()).map(l -> {
                    GamePlay n = new GamePlay();
                    BeanUtil.copyProperties(l, n);
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] gamePlayNum = new String[]{"orderUserNum", "orderNum", "orderMoneyAll"};
        listToMap("GamePlay", gamePlayNum, gamePlay, resultMap);

//        直播
        flag.set(1);

        VoiceOverviewListDTO broadcastOverview = new VoiceOverviewListDTO();
        BeanUtil.copyProperties(query, broadcastOverview);
        broadcastOverview.setDataFrom(1);
        broadcastOverview.setRoomCategoryId(8);
        broadcastOverview.setStartDate(DateUtil.formatDate(statTimeStart));
        broadcastOverview.setEndDate(DateUtil.formatDate(statTimeEnd));

        List<Broadcast> broadcast = voiceOverviewService.list(broadcastOverview).stream()
                .sorted(Comparator.<VoiceOverviewVO>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed())
                .map(l -> {
                    Broadcast n = new Broadcast();
                    BeanUtil.copyProperties(l, n);
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] broadcastNum = new String[]{"enterRoomUserNum", "stayFiveMinUserNum", "consumeUserNum", "consumeNum", "virtualMoneyAll"};
        listToMap("Broadcast", broadcastNum, broadcast, resultMap);
//        交友派对
        flag.set(1);

        VoiceOverviewListDTO partyOverview = new VoiceOverviewListDTO();
        BeanUtil.copyProperties(query, partyOverview);
        partyOverview.setDataFrom(1);
        partyOverview.setStartDate(DateUtil.formatDate(statTimeStart));
        partyOverview.setEndDate(DateUtil.formatDate(statTimeEnd));

        List<Party> party = voiceOverviewService.list(partyOverview).stream()
                .sorted(Comparator.<VoiceOverviewVO>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed())
                .map(l -> {
                    Party n = new Party();
                    BeanUtil.copyProperties(l, n);
                    broadcast.stream().filter(b -> Objects.equals(b.getStatDate(), n.getStatDate()))
                            .findAny().ifPresent(b -> {
                        n.setEnterRoomUserNum(n.getEnterRoomUserNum() - b.getEnterRoomUserNum());
                        n.setStayFiveMinUserNum(n.getStayFiveMinUserNum() - b.getStayFiveMinUserNum());
                        n.setConsumeUserNum(n.getConsumeUserNum() - b.getConsumeUserNum());
                        n.setConsumeNum(n.getConsumeNum() - b.getConsumeNum());
                        n.setVirtualMoneyAll(n.getVirtualMoneyAll().subtract(b.getVirtualMoneyAll()));
                    });
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] partyNum = new String[]{"enterRoomUserNum", "stayFiveMinUserNum", "consumeUserNum", "consumeNum", "virtualMoneyAll"};
        listToMap("Party", partyNum, party, resultMap);
//        有声陪伴
        flag.set(1);

        GameCategoryListBO companyOverview = new GameCategoryListBO();
        BeanUtil.copyProperties(query, companyOverview);
        companyOverview.setCategories(Collections.singletonList("有声陪伴"));
        companyOverview.setStartDate(DateUtil.formatDate(statTimeStart));
        companyOverview.setEndDate(DateUtil.formatDate(statTimeEnd));

        List<Company> company = gameCategoryService.list(companyOverview).getList().stream()
                .sorted(Comparator.<GameCategoryStatVO>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed()).map(l -> {
                    Company n = new Company();
                    BeanUtil.copyProperties(l, n);
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());

        String[] companyNum = new String[]{"orderUserNum", "orderNum", "orderMoneyAll"};
        listToMap("Company", companyNum, company, resultMap);
//        音乐
        flag.set(1);

        VoiceOverviewListDTO musicOverview = new VoiceOverviewListDTO();
        BeanUtil.copyProperties(query, musicOverview);
        musicOverview.setDataFrom(1);
        musicOverview.setRoomCategoryId(9);
        musicOverview.setStartDate(DateUtil.formatDate(statTimeStart));
        musicOverview.setEndDate(DateUtil.formatDate(statTimeEnd));

        List<Company> music = voiceOverviewService.list(musicOverview).stream()
                .sorted(Comparator.<VoiceOverviewVO>comparingLong(g ->
                        DateUtil.parse(g.getStatDate()).getTime()
                ).reversed())
                .map(l -> {
                    Company n = new Company();
                    n.setStatDate(l.getStatDate());
                    n.setOrderUserNum(l.getConsumeUserNum());
                    n.setOrderNum(l.getConsumeNum());
                    n.setOrderMoneyAll(l.getVirtualMoneyAll());
                    n.setFlag(flag.getAndIncrement());
                    return n;
                }).collect(Collectors.toList());


        String[] musicNum = new String[]{"orderUserNum", "orderNum", "orderMoneyAll"};
        listToMap("Music", musicNum, music, resultMap);

        return resultMap;

    }

    private static List<Map<String, Object>> objToMap(List<?> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().map(map -> BeanUtil.beanToMap(map)).collect(Collectors.toList());
    }

    public void listToMap(String name, String[] num, List<?> list, Map<String, Object> resultMap) {
        List<Map<String, Object>> mapList = objToMap(list);
        for (String s : num) {
            Map<String, Object> map = mapList
                    .stream()
                    .peek(a -> log.error(new Gson().toJson(a)))
                    .collect(Collectors.toMap(p -> s + "_" + p.get("flag"),
                            p -> NumberUtil.toStr(new BigDecimal(Optional.ofNullable(p.get(s)).orElse(0).toString()).doubleValue())));
            // 环比 取出1、2、8
            BigDecimal newUserNum1 = map.get(s + "_1") == null ? BigDecimal.ZERO : new BigDecimal(map.get(s + "_1").toString());
            BigDecimal newUserNum2 = map.get(s + "_2") == null ? BigDecimal.ZERO : new BigDecimal(map.get(s + "_2").toString());
            BigDecimal newUserNum8 = map.get(s + "_8") == null ? BigDecimal.ZERO : new BigDecimal(map.get(s + "_8").toString());
            map.put(s + "_day", newUserNum2.compareTo(BigDecimal.ZERO) == 0 ? "0%" : newUserNum1.subtract(newUserNum2).divide(newUserNum2, 4, RoundingMode.UP)
                    .multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            map.put(s + "_week", newUserNum8.compareTo(BigDecimal.ZERO) == 0 ? "0%" : newUserNum1.subtract(newUserNum8).divide(newUserNum8, 4, RoundingMode.UP)
                    .multiply(new BigDecimal("100")).setScale(2, RoundingMode.DOWN) + "%");
            resultMap.put(name + "_" + s, Arrays.asList(map));
        }
    }
}
